home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/udp.h>
- #include <linux/icmp.h>
- #include <linux/if.h>
- #include <linux/ip_fw.h>
- #include <unistd.h>
- #include <ctype.h>
- #include <string.h>
- #include "netconf.h"
- #include "../misc/misc.h"
-
- #ifndef IP_FW_POLICY_IN
- /* These are just here so it compiles */
- #define IP_FW_POLICY_IN 0
- #define IP_FW_FLUSH_IN 1
- #define IP_FW_APPEND_IN 2
- #define IP_FW_POLICY_OUT 3
- #define IP_FW_FLUSH_OUT 4
-
- #define FIREWALL_NONE
- #endif
-
-
-
-
-
- static int sockfd = -1;
-
- int ipfw_append (
- int doit,
- SSTRING *collect,
- int command,
- struct ip_fw &b)
- {
- int ret = 0;
- if (collect != NULL){
- /* #Specification: firewall / formatting output
- While programming the firewall, we compose in a string
- the same format as will be created by the kernel in one
- of the file /proc/net/ip_input or /proc/net/ip_forward.
-
- So it become possible to compare this with the current
- content of those file and tell if something as to be done.
- */
- #ifndef FIREWALL_NONE
- char buffer[300];
- int len=sprintf(buffer,"%08lX/%08lX->%08lX/%08lX %.16s %08lX %X "
- ,ntohl(b.fw_src.s_addr),ntohl(b.fw_smsk.s_addr)
- ,ntohl(b.fw_dst.s_addr),ntohl(b.fw_dmsk.s_addr)
- ,(b.fw_vianame)[0] ? b.fw_vianame : "-"
- ,ntohl(b.fw_via.s_addr),b.fw_flg);
- len+=sprintf(buffer+len,"%u %u %-9lu %-9lu"
- ,b.fw_nsp,b.fw_ndp, b.fw_pcnt,b.fw_bcnt);
- for (int p = 0; p < IP_FW_MAX_PORTS; p++)
- len+=sprintf(buffer+len, " %u", b.fw_pts[p]);
- sprintf(buffer+len, " A%02X X%02X\n", b.fw_tosand, b.fw_tosxor);
-
- collect->append (buffer);
- #endif
- }
- if (doit){
- ret = setsockopt (sockfd, IPPROTO_IP, command
- ,&b,sizeof(struct ip_fw));
- if (ret != 0){
- xconf_error ("error append firewall %d(%s)",errno,strerror(errno));
- }
- }
- return ret;
- }
-
- int ipfw_flush (
- int doit,
- SSTRING *,
- int command)
- {
- int ret = 0;
- if (doit){
- int data = 0;
- ret = setsockopt (sockfd, IPPROTO_IP, command,&data,sizeof(data));
- if (ret != 0){
- xconf_error ("error flush firewall %d(%s)",errno,strerror(errno));
- }
- }
- return ret;
- }
-
- int ipfw_policy (
- int doit,
- SSTRING *collect,
- int command,
- int policy)
- {
- int ret = 0;
- if (collect != NULL){
- char *ctl = NULL;
- switch (command){
- case IP_FW_POLICY_IN:
- ctl = "IP firewall input rules, default %d\n";
- break;
- case IP_FW_POLICY_OUT:
- ctl = "IP firewall output rules, default %d\n";
- break;
- case IP_FW_POLICY_FWD:
- ctl = "IP firewall forward rules, default %d\n";
- break;
- }
- char buf[100];
- sprintf(buf,ctl,policy);
- collect->append (buf);
- }
- if (doit){
- ret = setsockopt (sockfd, IPPROTO_IP, command,&policy,sizeof(policy));
- }
- return ret;
- }
-
- /*
- Initialise the sockfd needed to program the rules
- Return -1 if any error.
- */
- int ipfw_open ()
- {
- sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- return sockfd;
- }
-
-
- void ipfw_close()
- {
- close (sockfd);
- sockfd = -1;
- }
-
- #ifndef FIREWALL_NONE
- /*
- Translate and validate an ASCII IP addr.
- */
- static int ipfw_a2ip (const char *adr, struct in_addr &ina)
- {
- int num4[4];
- int ret = device_aip24 (adr,num4);
- if (ret != -1){
- unsigned long ipa = (num4[0] <<24) | (num4[1] << 16)
- | (num4[2] << 8) | num4[3];
- ina.s_addr = htonl (ipa);
- }
- return ret;
- }
-
- static int ipfw_setrange (
- const char *range,
- struct ip_fw &bf,
- int flag,
- int noport,
- unsigned short &nb)
- {
- const char *s = str_skip (range);
- if (s[0] != '\0'){
- bf.fw_flg |= flag;
- bf.fw_pts[noport++] = atoi(s);
- s = str_skipdig (s);
- s = str_skip (s);
- if (*s == ':') s++;
- s = str_skip (s);
- bf.fw_pts[noport++] = atoi(s);
- nb = 2;
- }
- return noport;
- }
-
- static int ipfw_setports (
- const char *ports,
- struct ip_fw &bf,
- unsigned short &nb,
- int noport,
- const char *proto)
- {
- while (1){
- ports = str_skip (ports);
- if (ports[0] == '\0'){
- break;
- }else{
- char word[200];
- ports = str_copyword(word,ports);
- int port = atoi(word);
- struct servent *serv = getservbyname (word,proto);
- if (serv != NULL) port = ntohs(serv->s_port);
- bf.fw_pts[noport++] = port;
- nb++;
- }
- }
- return noport;
- }
-
- /*
- Return -1 if anything is invalid
- */
- int ipfw_baseinit (
- const char *iface,
- const char *protocol,
- const char *ip_src,
- const char *msk_src,
- const char *sport_range,
- const char *sports,
- const char *ip_dst,
- const char *msk_dst,
- const char *dport_range,
- const char *dports,
- struct ip_fw &bf)
- {
- memset (&bf,0,sizeof(bf));
- int ret = ipfw_a2ip (ip_src,bf.fw_src);
- ret |= ipfw_a2ip (msk_src,bf.fw_smsk);
- bf.fw_src.s_addr &= bf.fw_smsk.s_addr;
- ret |= ipfw_a2ip (ip_dst,bf.fw_dst);
- ret |= ipfw_a2ip (msk_dst,bf.fw_dmsk);
- bf.fw_dst.s_addr &= bf.fw_dmsk.s_addr;
- /* #Specification: firewall / iface / assumption
- We assume that all network device do begin with a letter.
- This way we differentiate IP number for interface from name
- */
- if (isalpha(iface[0])){
- strcpy (bf.fw_vianame,iface);
- }else{
- ret |= ipfw_a2ip (iface,bf.fw_via);
- }
- if (stricmp(protocol,"all")==0){
- bf.fw_flg = IP_FW_F_ALL;
- }else if (stricmp(protocol,"tcp")==0){
- bf.fw_flg = IP_FW_F_TCP;
- }else if (stricmp(protocol,"udp")==0){
- bf.fw_flg = IP_FW_F_UDP;
- }else if (stricmp(protocol,"icmp")==0){
- bf.fw_flg = IP_FW_F_ICMP;
- }else{
- ret = -1;
- }
- int noport = ipfw_setrange (sport_range,bf,IP_FW_F_SRNG,0,bf.fw_nsp);
- noport = ipfw_setports (sports,bf,bf.fw_nsp,noport,protocol);
- noport = ipfw_setrange (dport_range,bf,IP_FW_F_DRNG,noport,bf.fw_ndp);
- ipfw_setports (dports,bf,bf.fw_ndp,noport,protocol);
-
- bf.fw_tosand = 0xFF;
- bf.fw_tosxor = 0x00;
- bf.fw_flg |= IP_FW_F_ACCEPT;
- return ret;
- }
-
- #else
-
- int ipfw_baseinit (
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- const char *,
- struct ip_fw &)
- {
- return -1;
- }
-
- #endif
-